林嶔 (Lin, Chin)
Lesson 16
自由度相當低,只能畫幾種的圖形
超大型數據在html格式下會用掉非常多資源
– ui.R
library(shiny)
fluidPage(
fluidRow(
column(width = 4,
plotOutput("plot1", height = 350,
click = "plot_click",
dblclick = dblclickOpts(id = "plot_dblclick"),
hover = hoverOpts(id = "plot_hover"),
brush = brushOpts(id = "plot_brush")
)
)
),
fluidRow(
column(width = 3,
verbatimTextOutput("click_info")
),
column(width = 3,
verbatimTextOutput("dblclick_info")
),
column(width = 3,
verbatimTextOutput("hover_info")
),
column(width = 3,
verbatimTextOutput("brush_info")
)
)
)
– server.R
library(shiny)
data(cars)
dat = cars
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
plot(dat)
})
output$click_info <- renderPrint({
cat("input$plot_click:\n")
str(input$plot_click)
})
output$hover_info <- renderPrint({
cat("input$plot_hover:\n")
str(input$plot_hover)
})
output$dblclick_info <- renderPrint({
cat("input$plot_dblclick:\n")
str(input$plot_dblclick)
})
output$brush_info <- renderPrint({
cat("input$plot_brush:\n")
str(input$plot_brush)
})
})
– 這邊需要用到兩個新函數:reactiveValues()、observe()和observeEvent()
library(shiny)
fluidPage(
fluidRow(
column(width = 4,
plotOutput("plot1", height = 400,
brush = brushOpts(id = "plot1_brush", resetOnNew = TRUE))
),
column(width = 4,
plotOutput("plot2", height = 400)
),
column(width = 4,
plotOutput("plot3", height = 400,
dblclick = "plot3_dblclick",
brush = brushOpts(id = "plot3_brush", resetOnNew = TRUE))
)
)
)
library(shiny)
data(cars)
dat = cars
shinyServer(function(input, output) {
ranges1 = reactiveValues(x = NULL, y = NULL)
observe({
brush1 = input$plot1_brush
if (!is.null(brush1)) {
ranges1$x = c(brush1$xmin, brush1$xmax)
ranges1$y = c(brush1$ymin, brush1$ymax)
} else {
ranges1$x = NULL
ranges1$y = NULL
}
})
output$plot1 <- renderPlot({
plot(dat)
})
output$plot2 <- renderPlot({
plot(dat, xlim = ranges1$x, ylim = ranges1$y)
})
ranges2 <- reactiveValues(x = NULL, y = NULL)
output$plot3 <- renderPlot({
plot(dat, xlim = ranges2$x, ylim = ranges2$y)
})
observeEvent(input$plot3_dblclick, {
brush2 <- input$plot3_brush
if (!is.null(brush2)) {
ranges2$x <- c(brush2$xmin, brush2$xmax)
ranges2$y <- c(brush2$ymin, brush2$ymax)
} else {
ranges2$x <- NULL
ranges2$y <- NULL
}
})
})
假設你未來想要做人工智慧研究,我們在教會電腦之前自己必須先做一次給他看。
目前我們的任務是,請你找出圖片中的人類位置在哪,請到這裡下載範例檔案
– 我們先看看裡面的一個文字檔案,而這個檔案描述的是5張圖的人類位置在哪:
box_info = read.csv("examples/label.csv", header = TRUE, stringsAsFactors = FALSE)
box_info
## obj_name col_left col_right row_bot row_top prob img_id
## 1 person 0.60728125 0.7782344 0.8139110 0.1637471 1 1
## 2 person 0.00000000 0.0971250 0.7015925 0.6154801 1 1
## 3 person 0.50981250 0.6211250 0.8687150 0.4078505 1 2
## 4 person 0.01529687 0.2058281 0.9194159 0.3903271 1 2
## 5 person 0.79756250 0.9907812 0.9042757 0.4001636 1 2
## 6 person 0.32854688 0.6720156 0.8738333 0.2985208 1 3
## 7 person 0.88721875 0.9362500 0.7515368 0.5911255 1 4
## 8 person 0.39248437 0.4289219 0.3639394 0.2303463 1 4
## 9 person 0.47934375 0.4961250 0.6005000 0.5788542 1 5
## 10 person 0.76668750 0.7721250 0.5681875 0.5610833 1 5
library(jpeg)
library(imager)
Show_img = function (img, box_info = NULL, col_bbox = '#FFFFFF00', col_label = '#FF0000FF') {
par(mar = rep(0, 4))
plot(NA, xlim = c(0, 1), ylim = c(1, 0), xaxt = "n", yaxt = "n", bty = "n")
img = (img - min(img))/(max(img) - min(img))
img = as.raster(img)
rasterImage(img, 0, 1, 1, 0, interpolate=FALSE)
if (!is.null(box_info)) {
if (nrow(box_info) > 0) {
for (i in 1:nrow(box_info)) {
size = max(box_info[i,3] - box_info[i,2], 0.2)
rect(xleft = box_info[i,2], xright = box_info[i,2] + 0.06*sqrt(size)*nchar(box_info[i,1]),
ybottom = box_info[i,5] + 0.08*sqrt(size), ytop = box_info[i,5],
col = col_label, border = col_label, lwd = 0)
text(x = box_info[i,2] + 0.03*sqrt(size) * nchar(box_info[i,1]),
y = box_info[i,5] + 0.04*sqrt(size),
labels = box_info[i,1],
col = 'white', cex = 1.5*sqrt(size), font = 2)
rect(xleft = box_info[i,2], xright = box_info[i,3],
ybottom = box_info[i,4], ytop = box_info[i,5],
col = col_bbox, border = col_label, lwd = 5*sqrt(size))
}
}
}
}
img = readJPEG("examples/2.jpeg")
Show_img(img, box_info[box_info[,"img_id"] == 2,])
img = readJPEG("examples/3.jpeg")
Show_img(img, box_info[box_info[,"img_id"] == 3,])
讓使用者能夠自己上傳一張圖片上去
框出物件的位置在哪,並選擇框選的物件為何(目前只有人類供選擇)
按下按鍵後紀錄框的位置
將資訊記錄在資料表內,而img_id設定為圖像的檔名
如果使用者覺得框錯了,可以把它刪除
使用者最終能下載該資料表
library(shiny)
library(DT)
library(jpeg)
library(imager)
fluidPage(
fluidRow(
column(width = 4,
fileInput("files", label = h4("Upload your jpeg image:"), multiple = FALSE, accept = "image/jpeg"),
br(),
radioButtons("obj", label = h4("Please select a object name:"), c("person" = "person")),
br(),
downloadButton("download", label = "Download file", class = NULL)
),
column(width = 7,
plotOutput("plot", height = 416, width = 416,
dblclick = "plot_dblclick",
brush = brushOpts(id = "plot_brush", resetOnNew = TRUE)),
br(),
actionButton("delete", strong("Delete selected box!"), icon("list-alt")),
br(),
br(),
DT::dataTableOutput('table')
)
)
)
library(shiny)
library(DT)
library(jpeg)
library(imager)
Show_img = function (img, box_info = NULL, col_bbox = '#FFFFFF00', col_label = '#FF0000FF') {
par(mar = rep(0, 4))
plot(NA, xlim = c(0, 1), ylim = c(1, 0), xaxt = "n", yaxt = "n", bty = "n")
img = (img - min(img))/(max(img) - min(img))
img = as.raster(img)
rasterImage(img, 0, 1, 1, 0, interpolate=FALSE)
if (!is.null(box_info)) {
if (nrow(box_info) > 0) {
for (i in 1:nrow(box_info)) {
size = max(box_info[i,3] - box_info[i,2], 0.2)
rect(xleft = box_info[i,2], xright = box_info[i,2] + 0.06*sqrt(size)*nchar(box_info[i,1]),
ybottom = box_info[i,5] + 0.08*sqrt(size), ytop = box_info[i,5],
col = col_label, border = col_label, lwd = 0)
text(x = box_info[i,2] + 0.03*sqrt(size) * nchar(box_info[i,1]),
y = box_info[i,5] + 0.04*sqrt(size),
labels = box_info[i,1],
col = 'white', cex = 1.5*sqrt(size), font = 2)
rect(xleft = box_info[i,2], xright = box_info[i,3],
ybottom = box_info[i,4], ytop = box_info[i,5],
col = col_bbox, border = col_label, lwd = 5*sqrt(size))
}
}
}
}
shinyServer(function(input, output) {
IMAGE = reactive({
if (is.null(input$files)) {return()} else {
img = readJPEG(input$files$datapath)
return(img)
}
})
MY_TABLE = reactiveValues(table = NULL)
output$plot = renderPlot({
img = IMAGE()
if (!is.null(input$files$name)) {
box_info = MY_TABLE$table
box_info = box_info[box_info[,"img_id"] == input$files$name,]
} else {
box_info = NULL
}
if (is.null(img)) {return()} else {
Show_img(img = img, box_info = box_info)
}
})
observeEvent(input$plot_dblclick, {
brush = input$plot_brush
if (!is.null(brush) & !is.null(input$files$name)) {
new_table = data.frame(obj_name = input$obj,
col_left = brush$xmin,
col_right = brush$xmax,
row_bot = brush$ymax,
row_top = brush$ymin,
prob = 1,
img_id = input$files$name,
stringsAsFactors = FALSE)
MY_TABLE$table = rbind(MY_TABLE$table, new_table)
}
})
observeEvent(input$delete, {
selection = as.numeric(input$table_rows_selected)
if (length(selection)!=0) {
MY_TABLE$table = MY_TABLE$table[-selection,]
}
})
output$table = DT::renderDataTable({
dat = MY_TABLE$table
if (is.null(dat)) {return()} else {
dat[,2] = round(dat[,2], 3)
dat[,3] = round(dat[,3], 3)
dat[,4] = round(dat[,4], 3)
dat[,5] = round(dat[,5], 3)
Result = DT::datatable(dat)
return(Result)
}
})
output$download = downloadHandler(
filename = function() {'label.csv'},
content = function(con) {
dat = MY_TABLE$table
if (is.null(dat)) {return()} else {
write.csv(dat, con, row.names = FALSE)
}
}
)
})
– 你應該有注意到你的App是沒有辦法用帳號密碼保護的,而要做這件事情確實是有難度,畢竟我們似乎是沒有學過兩個頁面的切換功能,那讓我們再google看看吧:
– 其中的第三個討論串:Starting Shiny app after password input就是在講這件事情
rm(list = ls())
library(shiny)
Logged = FALSE;
my_username <- "test"
my_password <- "test"
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),actionButton("Login", "Log in"))),
tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}")
)}
ui2 <- function(){tagList(tabPanel("Test"))}
ui = (htmlOutput("page"))
server = (function(input, output,session) {
USER <- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
}
}
}
}
}
})
observe({
if (USER$Logged == FALSE) {
output$page <- renderUI({
div(class="outer",do.call(bootstrapPage,c("",ui1())))
})
}
if (USER$Logged == TRUE)
{
output$page <- renderUI({
div(class="outer",do.call(navbarPage,c(inverse=TRUE,title = "Contratulations you got in!",ui2())))
})
print(ui)
}
})
})
#runApp(list(ui = ui, server = server))
– global.R
library(shiny)
Logged = FALSE;
my_username <- "test"
my_password <- "test"
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),actionButton("Login", "Log in"))),
tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}")
)}
ui2 <- function(){tagList(tabPanel("Test"))}
– ui.R
library(shiny)
htmlOutput("page")
library(shiny)
function(input, output,session) {
USER <- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
}
}
}
}
}
})
observe({
if (USER$Logged == FALSE) {
output$page <- renderUI({
div(class="outer",do.call(bootstrapPage,c("",ui1())))
})
}
if (USER$Logged == TRUE)
{
output$page <- renderUI({
div(class="outer",do.call(navbarPage,c(inverse=TRUE,title = "Contratulations you got in!",ui2())))
})
print(ui)
}
})
}
– global.R
library(shiny)
Logged = FALSE;
my_username <- "test"
my_password <- "test"
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),actionButton("Login", "Log in"))),
tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}")
)}
ui2 <- function(){tagList(tabPanel("Test",
sliderInput("obs", "Number of observations:", min = 0, max = 1000, value = 500),
plotOutput("distPlot")))}
– ui.R
library(shiny)
htmlOutput("page")
library(shiny)
function(input, output,session) {
USER <- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
}
}
}
}
}
})
observe({
if (USER$Logged == FALSE) {
output$page <- renderUI({
div(class="outer",do.call(bootstrapPage,c("",ui1())))
})
}
if (USER$Logged == TRUE)
{
output$page <- renderUI({
div(class="outer",do.call(navbarPage,c(inverse=TRUE,title = "Contratulations you got in!",ui2())))
})
print(ui)
output$distPlot = renderPlot({
# generate an rnorm distribution and plot it
dist = rnorm(input$obs)
hist(dist)
})
}
})
}
– 請你設計兩個頁面的程序,讓使用者在使用標註系統之前需要輸入帳號密碼!
library(shiny)
library(DT)
library(jpeg)
library(imager)
Logged = FALSE;
my_username <- "test"
my_password <- "test"
Show_img = function (img, box_info = NULL, col_bbox = '#FFFFFF00', col_label = '#FF0000FF') {
par(mar = rep(0, 4))
plot(NA, xlim = c(0, 1), ylim = c(1, 0), xaxt = "n", yaxt = "n", bty = "n")
img = (img - min(img))/(max(img) - min(img))
img = as.raster(img)
rasterImage(img, 0, 1, 1, 0, interpolate=FALSE)
if (!is.null(box_info)) {
if (nrow(box_info) > 0) {
for (i in 1:nrow(box_info)) {
size = max(box_info[i,3] - box_info[i,2], 0.2)
rect(xleft = box_info[i,2], xright = box_info[i,2] + 0.06*sqrt(size)*nchar(box_info[i,1]),
ybottom = box_info[i,5] + 0.08*sqrt(size), ytop = box_info[i,5],
col = col_label, border = col_label, lwd = 0)
text(x = box_info[i,2] + 0.03*sqrt(size) * nchar(box_info[i,1]),
y = box_info[i,5] + 0.04*sqrt(size),
labels = box_info[i,1],
col = 'white', cex = 1.5*sqrt(size), font = 2)
rect(xleft = box_info[i,2], xright = box_info[i,3],
ybottom = box_info[i,4], ytop = box_info[i,5],
col = col_bbox, border = col_label, lwd = 5*sqrt(size))
}
}
}
}
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),actionButton("Login", "Log in"))),
tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}")
)}
ui2 <- function(){tagList(tabPanel("Main page",
fluidRow(
column(width = 4,
fileInput("files", label = h4("Upload your jpeg image:"), multiple = FALSE, accept = "image/jpeg"),
br(),
radioButtons("obj", label = h4("Please select a object name:"), c("person" = "person")),
br(),
downloadButton("download", label = "Download file", class = NULL)
),
column(width = 7,
plotOutput("plot", height = 416, width = 416,
dblclick = "plot_dblclick",
brush = brushOpts(id = "plot_brush", resetOnNew = TRUE)),
br(),
actionButton("delete", strong("Delete selected box!"), icon("list-alt")),
br(),
br(),
DT::dataTableOutput('table')
)
)))}
library(shiny)
library(DT)
library(jpeg)
library(imager)
htmlOutput("page")
library(shiny)
library(DT)
library(jpeg)
library(imager)
function(input, output,session) {
USER <- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
}
}
}
}
}
})
observe({
if (USER$Logged == FALSE) {
output$page <- renderUI({
div(class="outer",do.call(bootstrapPage,c("",ui1())))
})
}
if (USER$Logged == TRUE)
{
output$page <- renderUI({
div(class="outer",do.call(navbarPage,c(inverse=TRUE,title = "Contratulations you got in!",ui2())))
})
print(ui)
IMAGE = reactive({
if (is.null(input$files)) {return()} else {
img = readJPEG(input$files$datapath)
return(img)
}
})
MY_TABLE = reactiveValues(table = NULL)
output$plot = renderPlot({
img = IMAGE()
if (!is.null(input$files$name)) {
box_info = MY_TABLE$table
box_info = box_info[box_info[,"img_id"] == input$files$name,]
} else {
box_info = NULL
}
if (is.null(img)) {return()} else {
Show_img(img = img, box_info = box_info)
}
})
observeEvent(input$plot_dblclick, {
brush = input$plot_brush
if (!is.null(brush) & !is.null(input$files$name)) {
new_table = data.frame(obj_name = input$obj,
col_left = brush$xmin,
col_right = brush$xmax,
row_bot = brush$ymax,
row_top = brush$ymin,
prob = 1,
img_id = input$files$name,
stringsAsFactors = FALSE)
MY_TABLE$table = rbind(MY_TABLE$table, new_table)
}
})
observeEvent(input$delete, {
selection = as.numeric(input$table_rows_selected)
if (length(selection)!=0) {
MY_TABLE$table = MY_TABLE$table[-selection,]
}
})
output$table = DT::renderDataTable({
dat = MY_TABLE$table
if (is.null(dat)) {return()} else {
dat[,2] = round(dat[,2], 3)
dat[,3] = round(dat[,3], 3)
dat[,4] = round(dat[,4], 3)
dat[,5] = round(dat[,5], 3)
Result = DT::datatable(dat)
return(Result)
}
})
output$download = downloadHandler(
filename = function() {'label.csv'},
content = function(con) {
dat = MY_TABLE$table
if (is.null(dat)) {return()} else {
write.csv(dat, con, row.names = FALSE)
}
}
)
}
})
}
– 請按這裡下載訓練資料
– 請按這裡下載答案提交格式
本次競賽的目標是利用2013年一整年的營運資料,預測2014年8/11至8/17的急診需求量
請利用下方指令進行讀檔
data.train=read.csv("kamera.csv",header=TRUE) #讀取kamera.csv,並存成"Data"這個物件(資料表格式)
head(data.train,5) #看"Data"這個資料表的前5個row
## date tz Hospital_PK Level PDR PBR total A01 A02 A03 A04
## 1 2013-01-01 [0,4) 6 1 3.00 0.2857143 0 4 1 1 0
## 2 2013-01-01 [0,4) 22 1 8.50 0.4722222 51 49 0 2 0
## 3 2013-01-01 [0,4) 35 1 18.75 0.3627451 74 58 8 8 0
## 4 2013-01-01 [0,4) 11 2 8.00 0.6176471 17 17 3 1 0
## 5 2013-01-01 [0,4) 12 2 6.50 0.5200000 13 8 4 1 0
## A05 A06 A07 A08 A09 A10 A11 A12 A13 A14 A15 A16 A17 C01 C02 C03 C04 C05
## 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
## 2 0 0 2 9 38 2 0 5 5 0 17 2913 0 0 0 0 0 0
## 3 1 0 1 30 43 0 0 9 11 0 39 677 1 3 0 0 0 1
## 4 2 1 0 1 8 8 0 0 0 0 5 384 0 0 0 0 0 0
## 5 0 0 1 0 11 1 0 5 7 0 0 0 0 0 0 3 0 0
## C06 B01 B02 B03 B04 B05 B06 Light
## 1 0 0 0 0 0 0 0 1
## 2 0 0 5 3 2 0 1 1
## 3 0 0 1 1 6 5 0 3
## 4 0 0 0 8 0 0 0 1
## 5 0 0 0 0 3 1 0 1
data.submit=read.csv("submission.csv",header=TRUE) #讀取submission.csv,並存成"Data"這個物件(資料表格式)
head(data.submit,5) #看"Data"這個資料表的前5個row
## date tz Hospital_PK total
## 1 2014-08-11 [0,4) 1 0
## 2 2014-08-11 [0,4) 6 0
## 3 2014-08-11 [0,4) 22 0
## 4 2014-08-11 [0,4) 35 0
## 5 2014-08-11 [0,4) 11 0
我們在這裡要使用Support Vector Machine(SVM)來進行資料的預測,這是一種機器學習的方式!
SVM在R裡面是利用e1071套件來執行的
– 我們將利用SVM進行預測,並比較兩種資料前處理模式
svm.data = data.frame(x1 = factor(data.train$tz), #x1 = 時段
x2 = factor(weekdays(as.Date(data.train$date))), #x2 = 星期[一-日]
x3 = factor(data.train$Hospital_PK), #x3 = 醫院
y = data.train$total) #y = 急診需求量
prob.train = 0.7 #設定訓練集比例
train_test = sample(c("train","test"), nrow(svm.data), #抽樣
replace = TRUE, prob = c(prob.train, 1-prob.train))
svm.data.train = svm.data[train_test=="train",]
svm.data.test = svm.data[train_test=="test",]
library(e1071)
model1 = svm(y~., data = svm.data.train) #利用data內所有變數對y做預測
pred.y1 = predict(model1,svm.data.test[,1:3]) #使用model1的資訊對測試集做預測
MSE1 = mean((svm.data.test$y - pred.y1)^2) #取得殘差平方的平均
print(MSE1)
## [1] 279.8662
library(e1071)
svm.data.train$y = log(svm.data.train$y+1) #對數處理
model2 = svm(y~., data = svm.data.train) #利用data內所有變數對y做預測
pred.y2 = predict(model2,svm.data.test[,1:3]) #使用model1的資訊對測試集做預測
pred.y2 = exp(pred.y2)-1 #指數轉換回來
MSE2 = mean((svm.data.test$y - pred.y2)^2) #取得殘差平方的平均
print(MSE2)
## [1] 113.3869
– 現在我們要用模型1為腳本,寫出一個WebApp來讓使用者能清楚的知道各時間點在這11間醫院的急診需求
– 而聰明的你一定猜的到,等等的練習題就是用模型2為腳本,從而改進我們WebApp的預測能力
library(e1071)
final.model = svm(y~., data = svm.data) #利用svm.data(原始資料)內所有變數對y做預測
save(final.model, file = "svmmodel.RData") #儲存預測模型至svmmodel.RData
rm(final.model) #移除final.model
load("svmmodel.RData") #重新載入final.model
#製作predict.data,讓我們能預測每週11家醫院在各時段的急診負荷量
predict.data = data.frame(x1 = factor(data.submit$tz), #x1 = 時段
x2 = factor(weekdays(as.Date(data.submit$date))), #x2 = 星期[一-日]
x3 = factor(data.submit$Hospital_PK)) #x3 = 醫院
save(predict.data, file = "predict.RData") #儲存預測資料的模板至predict.RData
#####################################################################################################
#以下步驟為提交答案所需(如果你也想參加資料挑戰賽)
data.submit[,4] = predict(final.model, predict.data[,1:3]) #使用final.model的資訊對predict.data做預測
write.csv(data.submit, "Finalresult.csv", row.names = FALSE) #寫出答案,可以上傳對答案
#####################################################################################################
load("svmmodel.RData") #重新載入final.model
load("predict.RData") #重新載入predict.data
#自訂欲預測之日期範圍,並產生demo.data
start.date = as.Date("2016-04-07")
end.date = as.Date("2016-04-17")
new.data = data.frame(date = seq(start.date, end.date, by=1))
new.data$x2 = weekdays(new.data$date)
demo.data = merge(predict.data, new.data, by = "x2")
#使用final.model對demo.data進行預測
demo.data$y = predict(final.model, demo.data[,1:3])
head(demo.data)
## x2 x1 x3 date y
## 1 星期一 [0,4) 1 2016-04-11 47.3510423
## 2 星期一 [0,4) 6 2016-04-11 0.5547009
## 3 星期一 [0,4) 22 2016-04-11 70.7381905
## 4 星期一 [0,4) 35 2016-04-11 130.4258435
## 5 星期一 [0,4) 11 2016-04-11 22.2921606
## 6 星期一 [0,4) 12 2016-04-11 20.7622100
– 在使用dygraphs套件之前,我們要先對demo.data做一些整理
TimeTable = table(demo.data[,c(4,2)]) #建立時間表格
HosTable = table(demo.data[,3]) #建立醫院表格
Time.series= paste0(seq(2,22,by=4),":00:00 CST") #將時段轉換為時間中位數
#產生Total.data儲存結果
Total.data = matrix(NA, ncol = length(HosTable), nrow = length(TimeTable))
colnames(Total.data) = paste0("Hospital",names(HosTable))
rownames(Total.data) = 1:nrow(Total.data)
#使用一個三層迴圈將Total.data填滿
for (i in 1:nrow(TimeTable)) {
for (j in 1:ncol(TimeTable)) {
for (k in 1:length(HosTable)) {
n = demo.data$y[demo.data$date==rownames(TimeTable)[i]&demo.data$x1==colnames(TimeTable)[j]&demo.data$x3==names(HosTable)[k]]
Total.data[(i-1)*ncol(TimeTable)+j,k] = n
}
rownames(Total.data)[(i-1)*ncol(TimeTable)+j] = paste(rownames(TimeTable)[i],Time.series[j],sep=" ")
}
}
head(Total.data)
## Hospital1 Hospital6 Hospital11 Hospital12
## 2016-04-07 2:00:00 CST 45.26475 0.001034993 21.09283 19.46670
## 2016-04-07 6:00:00 CST 47.75544 0.590673023 22.65763 22.72294
## 2016-04-07 10:00:00 CST 46.05991 -0.049235542 20.65645 21.28935
## 2016-04-07 14:00:00 CST 46.68220 0.100136663 21.71865 21.62580
## 2016-04-07 18:00:00 CST 44.35104 -0.099562259 20.29023 17.75060
## 2016-04-07 22:00:00 CST 47.52344 0.581704813 22.94151 21.44666
## Hospital13 Hospital14 Hospital16 Hospital17
## 2016-04-07 2:00:00 CST 14.18914 32.17005 10.82161 5.461864
## 2016-04-07 6:00:00 CST 16.98470 34.75889 13.66608 7.405919
## 2016-04-07 10:00:00 CST 15.60828 32.78517 12.15655 6.132014
## 2016-04-07 14:00:00 CST 16.09937 33.90180 12.90054 6.627555
## 2016-04-07 18:00:00 CST 13.10030 31.31449 10.09999 4.549515
## 2016-04-07 22:00:00 CST 16.10017 35.22103 13.59852 7.269719
## Hospital22 Hospital35 Hospital40
## 2016-04-07 2:00:00 CST 67.97906 125.9879 7.900088
## 2016-04-07 6:00:00 CST 71.17072 128.6981 10.118229
## 2016-04-07 10:00:00 CST 68.29214 126.7926 8.907765
## 2016-04-07 14:00:00 CST 68.98362 127.3150 9.436575
## 2016-04-07 18:00:00 CST 67.19249 125.1709 7.195305
## 2016-04-07 22:00:00 CST 70.91280 128.5247 10.100224
#使用dygraphs套件做可視化處理
library(dygraphs)
Time.plot = dygraph(Total.data)
Time.plot = dyOptions(Time.plot,stackedGraph = TRUE)
Time.plot = dyRangeSelector(Time.plot,height = 50)
Time.plot #展示Time.plot
#使用htmlwidgets套件儲存結果
library(htmlwidgets)
saveWidget(Time.plot, "Timeplot.html")
– 另外,為了增加WebApp的華麗程度,請先下載shinydashboard套件,讓我們能使用他的ui模板
library(shiny)
library(shinydashboard)
library(e1071)
library(DT)
library(dygraphs)
library(htmlwidgets)
dashboardPage(
skin="yellow",
dashboardHeader(
title="Emergency Room Demand Forecast",
titleWidth = 450
),
dashboardSidebar(
sidebarMenu(
menuItem("Time series plot", tabName = "PLOT", icon = icon("dashboard")),
menuItem("Raw data", tabName = "RAW", icon = icon("th")),
fluidRow(
column(12, align="center",
h2(p(strong(span(style="color:white","Date Range")))),
dateRangeInput("dates", label = "", start = Sys.Date(), end = Sys.Date()+6, min = Sys.Date(), max = Sys.Date()+100),
actionButton("submit",strong("Start to predict!"),icon("list-alt")),
tags$style(type='text/css', "#submit { vertical-align: middle; height: 40px; width: 85%; font-size: 20px;}")
)
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "PLOT",
dygraphOutput("timeplot", width = "100%", height = "800px"),
downloadButton("download1", label = "Download HTML plot", class = NULL)
),
tabItem(tabName = "RAW",
DT::dataTableOutput('table'),
downloadButton("download2", label = "Download raw data", class = NULL)
)
)
)
)
library(shiny)
library(shinydashboard)
library(e1071)
library(DT)
library(dygraphs)
library(htmlwidgets)
load("svmmodel.RData") #重新載入final.model
load("predict.RData") #重新載入predict.data
#註:如果將.RData檔案放置在WebApp的資料夾內,則只需要使用 load("svmmodel.RData") 即可
shinyServer(function(input, output) {
TOTAL.DATA = eventReactive(input$submit,{
#自訂欲預測之日期範圍,並產生demo.data
start.date = as.Date(input$dates[1])
end.date = as.Date(input$dates[2])
new.data = data.frame(date = seq(start.date, end.date, by=1))
new.data$x2 = weekdays(new.data$date)
demo.data = merge(predict.data, new.data, by = "x2")
#使用final.model對demo.data進行預測
demo.data$y = predict(final.model, demo.data[,1:3])
TimeTable = table(demo.data[,c(4,2)]) #建立時間表格
HosTable = table(demo.data[,3]) #建立醫院表格
Time.series= paste0(seq(2,22,by=4),":00:00 CST") #將時段轉換為時間中位數
#產生Total.data儲存結果
Total.data = matrix(NA, ncol = length(HosTable), nrow = length(TimeTable))
colnames(Total.data) = paste0("Hospital",names(HosTable))
rownames(Total.data) = 1:nrow(Total.data)
#使用一個三層迴圈將Total.data填滿(使用進度條監測運算時間)
withProgress(message = "In processing...",value=0,{
for (i in 1:nrow(TimeTable)) {
for (j in 1:ncol(TimeTable)) {
for (k in 1:length(HosTable)) {
n = demo.data$y[demo.data$date==rownames(TimeTable)[i]&demo.data$x1==colnames(TimeTable)[j]&demo.data$x3==names(HosTable)[k]]
Total.data[(i-1)*ncol(TimeTable)+j,k] = n
incProgress(1/(ncol(TimeTable)*nrow(TimeTable)*length(HosTable)))
}
rownames(Total.data)[(i-1)*ncol(TimeTable)+j] = paste(rownames(TimeTable)[i],Time.series[j],sep=" ")
}
}
})
#回傳Total.data
return(Total.data)
})
TIME.PLOT = reactive({
Total.data = TOTAL.DATA()
if (!is.null(Total.data)) {
Time.plot = dygraph(Total.data)
Time.plot = dyOptions(Time.plot,stackedGraph = TRUE)
Time.plot = dyRangeSelector(Time.plot,height = 50)
return(Time.plot) #返回Time.plot
}
})
output$timeplot = renderDygraph({
TIME.PLOT()
})
output$download1 = downloadHandler(
filename = function() {'Timeplot.html'},
content = function(con) {
Time.plot = TIME.PLOT()
saveWidget(Time.plot, con)
}
)
output$table = DT::renderDataTable({
dat = TOTAL.DATA()
if (!is.null(dat)) {
DT::datatable(dat, selection="none")
}
})
output$download2 = downloadHandler(
filename = function() {'Rawdata.csv'},
content = function(con) {
write.csv(TOTAL.DATA(), con, quote = FALSE)
}
)
})
– 你可能需要先利用下列程式碼,匯出使用對數轉化後的SVM model
– 另外,Prediction data可以用一樣的,但要注意預測完的y要記得做指數轉化回來唷
– 如果可以的話,利用radioButtons()&conditionalPanel(),讓使用者能選擇使用Model 1或Model 2(有空再練習)
library(e1071)
svm.data$y = log(svm.data$y+1)
final.model2 = svm(y~., data = svm.data) #利用svm.data(原始資料)內所有變數對y做預測
save(final.model2, file = "svmmodel2.RData") #儲存預測模型至svmmodel2.RData
另外,在上週的練習-2中,我們曾經在server內計算Cox model,請試著利用save()&load()簡化該程序
上週的程式碼
– ui.R
library(shiny)
library(survival)
library(googleVis)
fluidPage(
sliderInput("Age", "Please enter your age", min=40, max=80, value=50),
radioButtons("rx", "Please select a treatment group", c("1","2")),
htmlOutput("chart1")
)
– server.R
library(shiny)
library(survival)
library(googleVis)
######################################################
# 就是這個部份太多餘,請簡化這個部分
data(ovarian)
dat = ovarian
model <- coxph(Surv(futime, fustat) ~ age + rx, data = dat)
h0.hazard = basehaz(model,centered=FALSE)
h0.hazard$hazard.lag = c(0,h0.hazard$hazard[-nrow(h0.hazard)])
h0.hazard$hazard.dif = h0.hazard$hazard-h0.hazard$hazard.lag
h0.hazard = h0.hazard[,c(2,4)]
h0.hazard.extend = data.frame(time = 0:max(h0.hazard[,1]), hazard.dif = 0)
h0.hazard = h0.hazard[h0.hazard[,2]!=0,]
h0.hazard = rbind(h0.hazard.extend,h0.hazard)
h0.hazard = h0.hazard[order(h0.hazard[,1]),]
matrix.coef = matrix(model$coef,nrow=length(model$coef),ncol=1)
######################################################
shinyServer(function(input, output, session) {
output$chart1<- renderGvis({
NEW <- as.matrix(data.frame(age=input$Age,rx=as.numeric(input$rx))) #年齡=input$Age;組別=as.numeric(input$rx)
indv.hazardratio = exp(NEW%*%matrix.coef)
indv.hazard = indv.hazardratio*h0.hazard$hazard.dif
indv.cumhazard = cumsum(indv.hazard)
indv.cumrate = exp(-indv.cumhazard)
Predic.Survival = data.frame(time = h0.hazard$time, rate = indv.cumrate)
Predic.Survival[,2] = round(Predic.Survival[,2]*100,2)
Scatter <- gvisScatterChart(Predic.Survival,
options=list(
explorer="{actions: ['dragToZoom',
'rightClickToReset'],
maxZoomIn:0.05}",
legend="none",
lineWidth=2, pointSize=0,
vAxis="{title:'Survival (%)'}",
vAxes="[{viewWindowMode:'explicit',
viewWindow:{min:0, max:100}}]",
hAxis="{title:'Time (days)'}",
colors="['#ff0000']",
width=800, height=500))
Scatter
})
})
library(shiny)
library(shinydashboard)
library(e1071)
library(DT)
library(dygraphs)
library(htmlwidgets)
dashboardPage(
skin="yellow",
dashboardHeader(
title="Emergency Room Demand Forecast",
titleWidth = 450
),
dashboardSidebar(
sidebarMenu(
menuItem("Time series plot", tabName = "PLOT", icon = icon("dashboard")),
menuItem("Raw data", tabName = "RAW", icon = icon("th")),
fluidRow(
column(12, align="center",
h2(p(strong(span(style="color:white","Date Range")))),
dateRangeInput("dates", label = "", start = Sys.Date(), end = Sys.Date()+6, min = Sys.Date(), max = Sys.Date()+100),
actionButton("submit",strong("Start to predict!"),icon("list-alt")),
tags$style(type='text/css', "#submit { vertical-align: middle; height: 40px; width: 85%; font-size: 20px;}")
)
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "PLOT",
dygraphOutput("timeplot", width = "100%", height = "800px"),
downloadButton("download1", label = "Download HTML plot", class = NULL)
),
tabItem(tabName = "RAW",
DT::dataTableOutput('table'),
downloadButton("download2", label = "Download raw data", class = NULL)
)
)
)
)
library(shiny)
library(shinydashboard)
library(e1071)
library(DT)
library(dygraphs)
library(htmlwidgets)
load("svmmodel2.RData") #載入final.model2
load("predict.RData")
shinyServer(function(input, output) {
TOTAL.DATA = eventReactive(input$submit,{
start.date = as.Date(input$dates[1])
end.date = as.Date(input$dates[2])
new.data = data.frame(date = seq(start.date, end.date, by=1))
new.data$x2 = weekdays(new.data$date)
demo.data = merge(predict.data, new.data, by = "x2")
demo.data$y = predict(final.model2, demo.data[,1:3]) #請將final.model改成final.model2
demo.data$y = exp(demo.data$y)-1 #請對demo.data$y做指數轉換
TimeTable = table(demo.data[,c(4,2)])
HosTable = table(demo.data[,3])
Time.series= paste0(seq(2,22,by=4),":00:00 CST")
Total.data = matrix(NA, ncol = length(HosTable), nrow = length(TimeTable))
colnames(Total.data) = paste0("Hospital",names(HosTable))
rownames(Total.data) = 1:nrow(Total.data)
withProgress(message = "In processing...",value=0,{
for (i in 1:nrow(TimeTable)) {
for (j in 1:ncol(TimeTable)) {
for (k in 1:length(HosTable)) {
n = demo.data$y[demo.data$date==rownames(TimeTable)[i]&demo.data$x1==colnames(TimeTable)[j]&demo.data$x3==names(HosTable)[k]]
Total.data[(i-1)*ncol(TimeTable)+j,k] = n
incProgress(1/(ncol(TimeTable)*nrow(TimeTable)*length(HosTable)))
}
rownames(Total.data)[(i-1)*ncol(TimeTable)+j] = paste(rownames(TimeTable)[i],Time.series[j],sep=" ")
}
}
})
return(Total.data)
})
TIME.PLOT = reactive({
Total.data = TOTAL.DATA()
if (!is.null(Total.data)) {
Time.plot = dygraph(Total.data)
Time.plot = dyOptions(Time.plot,stackedGraph = TRUE)
Time.plot = dyRangeSelector(Time.plot,height = 50)
return(Time.plot)
}
})
output$timeplot = renderDygraph({
TIME.PLOT()
})
output$download1 = downloadHandler(
filename = function() {'Timeplot.html'},
content = function(con) {
Time.plot = TIME.PLOT()
saveWidget(Time.plot, con)
}
)
output$table = DT::renderDataTable({
dat = TOTAL.DATA()
if (!is.null(dat)) {
DT::datatable(dat, selection="none")
}
})
output$download2 = downloadHandler(
filename = function() {'Rawdata.csv'},
content = function(con) {
write.csv(TOTAL.DATA(), con, quote = FALSE)
}
)
})
library(survival)
data(ovarian)
dat = ovarian
model <- coxph(Surv(futime, fustat) ~ age + rx, data = dat)
h0.hazard = basehaz(model,centered=FALSE)
h0.hazard$hazard.lag = c(0,h0.hazard$hazard[-nrow(h0.hazard)])
h0.hazard$hazard.dif = h0.hazard$hazard-h0.hazard$hazard.lag
h0.hazard = h0.hazard[,c(2,4)]
h0.hazard.extend = data.frame(time = 0:max(h0.hazard[,1]), hazard.dif = 0)
h0.hazard = h0.hazard[h0.hazard[,2]!=0,]
h0.hazard = rbind(h0.hazard.extend,h0.hazard)
h0.hazard = h0.hazard[order(h0.hazard[,1]),]
matrix.coef = matrix(model$coef,nrow=length(model$coef),ncol=1)
save(h0.hazard, matrix.coef, file = "matrices.RData") #儲存預測模型至matrices.RData
library(shiny)
library(googleVis)
fluidPage(
sliderInput("Age", "Please enter your age", min=40, max=80, value=50),
radioButtons("rx", "Please select a treatment group", c("1","2")),
htmlOutput("chart1")
)
library(shiny)
library(googleVis)
load("matrices.RData") #載入h0.hazard & matrix.coef
shinyServer(function(input, output, session) {
output$chart1<- renderGvis({
NEW <- as.matrix(data.frame(age=input$Age,rx=as.numeric(input$rx))) #年齡=input$Age;組別=as.numeric(input$rx)
indv.hazardratio = exp(NEW%*%matrix.coef)
indv.hazard = indv.hazardratio*h0.hazard$hazard.dif
indv.cumhazard = cumsum(indv.hazard)
indv.cumrate = exp(-indv.cumhazard)
Predic.Survival = data.frame(time = h0.hazard$time, rate = indv.cumrate)
Predic.Survival[,2] = round(Predic.Survival[,2]*100,2)
Scatter <- gvisScatterChart(Predic.Survival,
options=list(
explorer="{actions: ['dragToZoom',
'rightClickToReset'],
maxZoomIn:0.05}",
legend="none",
lineWidth=2, pointSize=0,
vAxis="{title:'Survival (%)'}",
vAxes="[{viewWindowMode:'explicit',
viewWindow:{min:0, max:100}}]",
hAxis="{title:'Time (days)'}",
colors="['#ff0000']",
width=800, height=500))
Scatter
})
})
– 關於使用shiny套件的學習資源,可以參考shiny的官方網站
– 若是你想要加強R的可視化處理,我推薦htmlwidgets for R以及googleVis Tutorial
– 但注意,免費帳戶每月僅能讓App運作25小時,並且只能上傳5個App
– 除此之外,如果你的原始碼有重要的商業價值,建議還是自建server
首先,你需要先到shinyapps.io上申請帳號
接著,請利用下面代碼安裝devtools套件及shinyapps套件
install.packages("devtools")
library(devtools)
devtools::install_github('rstudio/shinyapps')
library(shinyapps)
上面那些動作完成之後,接著你已經可以用非常簡單的方式來分享你寫好的App了。
請你回到ui.R或server.R的編輯視窗內,並且先按RunApp,然後我們會看到左上角有一個Publish的按鍵。
– 點選Publish後,會出現個小視窗,指定檔名後(這也是你未來的網址名稱)就可以上傳至shinyapps.io了